﻿using Microsoft.ML.OnnxRuntime;
using Microsoft.ML.OnnxRuntime.Tensors;
using OpenCvSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp
{
    public class OnnxHelper
    {

        private static readonly string modelPath = @"E:/data/var/flygo/AI/onnx/defect_recgon_X.onnx";
        private static readonly float confThreshold = 0.45f;
        private static readonly float nmsThreshold = 0.45f;
        private static readonly int MODEL_SIZE = 640;
        private static readonly string[] labels = new string[]{"组件面板破裂", "组件积灰", "鸟粪遮挡", "组串短接接地", "组件热斑", "常规二极管故障", "组件缺失",
                "双排组串空载", "横排二极管故障", "杂草遮挡", "组件空载", "单排组串空载", "其他遮挡"};

        public const int NUM_INPUT_ELEMENTS = 3 * 640 * 640;
        public static long[] INPUT_SHAPE = { 1, 3, 640, 640 };

        private float scale = 1;

        SessionOptions sessionOptions;
        InferenceSession onnxSession;
        // 创建输入Tensor
        Tensor<float> inputTensor = new DenseTensor<float> (new[] { 1, 3, MODEL_SIZE, MODEL_SIZE });
        
        List<NamedOnnxValue> inputContainer;
        IDisposableReadOnlyCollection<DisposableNamedOnnxValue> resultInfer;
        DisposableNamedOnnxValue[] resultOnnxValue;
     
        Tensor<float> resultTensors;
        public void detect(string imagePath)
        {
            initOptionsAndcreateSession(imagePath);

            // 创建输入Tensor
            inputTensor = new DenseTensor<float>(new[] { 1, 3, MODEL_SIZE, MODEL_SIZE });
            // 创建输入容器
            inputContainer = new List<NamedOnnxValue>();
            // 原图
            Mat rawImageMat = new Mat(imagePath);
            int rawImageRows = rawImageMat.Rows;
            int rawImageCols = rawImageMat.Cols;
            int rawImageWidth = rawImageMat.Width;
            int rawImageHeight = rawImageMat.Height;

            // 图片缩放
            Mat destIamgeMat = new Mat();
            // 将图片转为RGB通道
            Cv2.CvtColor(rawImageMat, destIamgeMat, ColorConversionCodes.BGR2RGB);
            scale = Math.Min((float)MODEL_SIZE / rawImageCols, (float)MODEL_SIZE / rawImageRows);
            Size resize = new Size(rawImageWidth * scale, rawImageHeight * scale);
            Cv2.Resize(destIamgeMat, destIamgeMat, resize);
          
            int destImageRows = destIamgeMat.Rows;
            int destImageCols = destIamgeMat.Cols;
            int destImageWidth = destIamgeMat.Width;
            int destImageHeight = destIamgeMat.Height;

            for (int y = 0; y < destImageHeight; y++)
            {
                for (int x = 0; x < destImageWidth; x++)
                {
                    inputTensor[0, 0, y, x] = destIamgeMat.At<Vec3b>(y, x)[0] / 255f;
                    inputTensor[0, 1, y, x] = destIamgeMat.At<Vec3b>(y, x)[1] / 255f;
                    inputTensor[0, 2, y, x] = destIamgeMat.At<Vec3b>(y, x)[2] / 255f;
                }
            }

            // 将输入参数放入参数容器 并指定容器名称
            inputContainer.Add(NamedOnnxValue.CreateFromTensor("images", inputTensor));
            resultInfer = onnxSession.Run(inputContainer);
            resultOnnxValue = resultInfer.ToArray();
            resultTensors = resultOnnxValue[0].AsTensor<float>();
            float[] result_array = new float[8400 * 84];
            result_array = resultTensors.ToArray();
             
        }


        private void initOptionsAndcreateSession(string modelPath)
        {
            // 创建输出会话, 用户输出模型读取信息
            sessionOptions = new SessionOptions();
            sessionOptions.LogSeverityLevel = OrtLoggingLevel.ORT_LOGGING_LEVEL_INFO;
            // 设置在CPU上运行
            sessionOptions.AppendExecutionProvider_CPU(0);
            // 创建推理模型类, 读取本地模型文件
            onnxSession = new InferenceSession(modelPath, sessionOptions);
        }
    }
}
